/*
 * © 2010 Autodata Solutions Company. All Rights Reserved
 * This source code is the confidential and proprietary information of Autodata Solutions Company.
 * The user shall not, in whole or in part, copy, publish, disclose or make any use of this source code
 * without the prior written consent of Autodata Solutions Company.
 */
Ext.ns('net.autodata.compare.data');
(function () {
	
	var CacheCollection = Ext.extend(Ext.util.MixedCollection, {
		
		get: function (key, incHitCount) 
		{
			var o = CacheCollection.superclass.get.call(this, key);
			if (o && incHitCount) {
				o.hitCount++;
			}
			return o;
		}
	});
	
	/**
	 * @class EditorialHttpCacheProxy
	 * @extends net.autodata.data.HttpCacheProxy
	 * @namespace net.autodata.compare.data
	 */
	var Proxy = Ext.extend(net.autodata.data.HttpCacheProxy, {
		
		constructor: function ()
		{
			Proxy.superclass.constructor.apply(this, arguments);
			var api = {};
			api[Ext.data.Api.actions.read] = true;
			this.api = api;
			
			this.url = String.format('{0}/Ajax/Compare/Editorial', ASC.cfg.getLocaleContextPath());
		},
		
		/**
		 * @method getCache
		 * @type Ext.util.MixedCollection
		 */
		getCache: function ()
		{	
			var cache;
			return function () {
				if (!cache) {
					cache = new CacheCollection(false, function (o) { return o.acode});
				}
				return cache;
			};
		}(),
		
		/**
	     * @cfg {Function} doRequest Abstract method that should be implemented in all subclasses.  Note: Should only be used by custom-proxy developers.
	     * (e.g.: {@link Ext.data.HttpProxy#doRequest HttpProxy.doRequest},
	     * {@link Ext.data.DirectProxy#doRequest DirectProxy.doRequest}).
	     */
		doRequest: function (action, rs, params, reader, callback, scope, options)
		{	
			
			var cache = this.getCache();
			
			//copy the acodes to a temp object so we can remove items already found in the cache
			var acodes = [];
			
			//create a list of acodes that are not in the cache
			Ext.each(params.acodes, function (acode, index) {
				var o = this.useCache ? cache.get(acode) : undefined;
				if (!o) {
					acodes.push(acode);
				}			
			}, this);
			
			//Not all acodes were found in the cache and an ajax request must be made
			if (acodes.length > 0) {
				
				//copy the original params and overwrite the acode array
				var p = Ext.apply({}, params);
				p.acodes = acodes;
				
				var o = {
					originalParams: params,
					originalOptions: options
				};
				this.executeRequest(action, rs, p, reader, callback, scope, o);
				return;
			}
			
			//Everything can be sourced from the cache
			this.processResponseFromCache(params, reader, callback, scope, options);
		},
		
		/**
		 * NOTE: Should not call this method directly should be called by the base class when an ajax call is scucessful
		 * @private 
		 */
		processResponse: function (response, params, reader, callback, scope, options)
		{	
			//The options object was changed to pass the original params
			//The callee expects the options stored inside the options param
			var p = options.originalParams;
			var o = options.originalOptions;
			
			var cache = this.getCache();
			
			//Go through the response and cache the values then construct the reader's response from the cache
			if (this.useCache) {
				Ext.each(response, function (item) {
					//set the hitCount to -1 because the processResponseFromCache will increament it to 0 the first time it is accessed
					cache.add({acode: item.acode, data: item, hitCount: -1});
				}, this);
				
				this.processResponseFromCache(p, reader, callback, scope, o);
			} else {
				//load the data as is
				this._processResponse(response, p, reader, callback, scope, o)
			}
		},
		
		_processResponse: function (response, params, reader, callback, scope, options)
		{
			
			var rows = [];
			
			Ext.each(response, function (record) {
				
				Ext.each(record.contents, function (item) {
					rows.push({
						acode: record.acode,
						title: item.title,
						summary: item.summary,
						url: item.url
					});
				}, this);
				
			}, this);
			
			try {
                var result = reader.readRecords({rows: rows});
            } catch (e) {
                this.fireEvent("loadexception", this, params, response, e);
                callback.call(scope || this, null, params, false);
                return;
            }
            
            this.fireEvent("load", this, response, options);
            callback.call(scope, result, options, true);
		},
		
		/**
		 * Pull the requested acodes from the cache
		 * @method _processResponse
		 * @private
		 */
		processResponseFromCache: function (params, reader, callback, scope, options)
		{			
			var cache = this.getCache();
			
			var response = [];
			Ext.each(params.acodes, function (acode) {
				var o = cache.get(acode, true);
				
				if (o) {
					response.push(o.data);
					ASC.log(String.format('data retrieved from cache Acode={0}; hitCount={1}', acode, o.hitCount));
				} else {
					response.push({});
				}
				
			}, this);
			
			this._processResponse(response, params, reader, callback, scope, options);
		}		
	});

	net.autodata.compare.data.EditorialHttpCacheProxy = Proxy;
	
})();